﻿namespace Pyramid.Hardware
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Pyramid.Hardware.Gates;

    public class MultilineDecoder
    {
        public MultilineDecoder(IEnumerable<ILine> inputBus)
        {
            int layerIndex = 0;
            IEnumerable<ILine> previousLayer = new ILine[] { FixedInputLine.True };

            foreach (var inputLine in inputBus.Reverse())
            {
                int decoderCount = (int)Math.Pow(3, layerIndex);

                var newLayer = new List<ILine>(decoderCount * 3);

                for (int decoderIndex = 0; decoderIndex < decoderCount; decoderIndex++)
                {
                    var decoder = new Decoder(inputLine);

                    var previousLine = previousLayer.ElementAt(decoderIndex);

                    newLayer.AddRange(decoder.OutputBus.Select(line => new AndGate(line, previousLine)).Cast<ILine>());
                }

                previousLayer = newLayer;
                layerIndex++;
            }

            OutputBus = previousLayer;
        }

        public IEnumerable<ILine> OutputBus
        {
            get;
            private set;
        }
    }
}
